import { nextTick } from "../utils/nextTick";
import { popTarget, pushTarget } from "./dep";

//通过wather更新
let id = 0;
class watcher {
  constructor(vm, exprOrfn, cb, options) {
    this.vm = vm;
    this.exprOrfn = exprOrfn;
    this.cb = cb;
    //computed
    this.lazy = options.lazy; //watcher有lazy 说明是computed
    this.dirty = this.lazy; //dirty  表示用户是否执行
    this.user = !!options.user;
    this.options = options;
    this.id = id++;
    this.deps = []; //存放dep
    this.depsId = new Set();
    //判断updataComponent是不是方法
    if (typeof exprOrfn === "function") {
      this.getter = exprOrfn; //用来更新视图
    } else {
      //字符串变成函数
      this.getter = function () {
        //深度监听
        let path = exprOrfn.split(".");
        let obj = vm;
        for (let i = 0; i < path.length; i++) {
          //循环得出实列上的值
          obj = obj[path[i]];
        }
        return obj;
      };
    }
    //初次更新视图
    this.value = this.lazy ? void 0 : this.get(); //保存第一次watch的初始值 判断是不是计算属性
    //watch 数组的深度克隆
    if (Array.isArray(this.value)) {
      debugger;
      this.value = [];
      for (const key in value) {
        this.value[key] = value[key];
      }
      Object.defineProperty(this.value, "__ob__", {
        enumerable: false,
        value: value.__ob__,
      });
      this.value.__proto__ = value.Prototype;
    }
  }
  run() {
    let value = this.get();
    let oldvalue = this.value;
    this.value = value;
    // 判断执行 handler 用户的wathre
    if (this.user) {
      this.cb.call(this.vm, value, oldvalue);
    }
  }
  get() {
    pushTarget(this); //添加watcher
    const value = this.getter.call(this.vm); //页面渲染
    popTarget();
    return value;
  }
  updata() {
    //b不要每次更新都调用get
    if (this.lazy) {
      this.dirty = true; //计算属性的watcer更改不需要刷新视图
    } else {
      queueWatcher(this);
    }
  }
  addDep(dep) {
    //去重
    let id = dep.id;
    if (!this.depsId.has(id)) {
      this.deps.push(dep);
      this.depsId.add(id);
      dep.addSub(this);
    }
  }
  evaluate() {
    this.value = this.get();
    this.dirty = false;
  }
  depend() {
    //相互收集watcher
    let i = this.deps.length;
    while (i--) {
      this.deps[i].depend();
    }
  }
}
//创建列队
let queue = []; //wath方法生成的和vue数据更新的都会被收集 只要是获取实列的数组get方法都会收集当前的wather
let has = {};
let pending = false;
function flushWatcher() {
  //防抖:用户触发多次只触发一次
  //最后走异步队列 走完了才能继续执行方法
  queue.forEach((item) => {
    item.run(), !item.user && item.cb();
  }); //同步执行 开始执行push的方法队列
  queue = [];
  has = {};
  pending = false;
}
function queueWatcher(watcher) {
  let id = watcher.id;
  if (!has[id]) {
    //去重
    queue.push(watcher); //持续添加方法到列队中
    has[id] = true;
    if (!pending) {
      nextTick(flushWatcher); //相当于定时器 //所有的同步数据更改之后执行此步用来更新
      pending = true;
    }
  }
}
export default watcher;
